/* PATH.C */

/*
	Copyright (C) 2010 by Lesnikov Andrey <ozkriff@gmail.com>
	This file is part of ozkriff_game_2.

	ozkriff_game_2 is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	ozkriff_game_2 is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with ozkriff_game_2.  If not, see <http://www.gnu.org/licenses/>.

	See the COPYING file for more details.
*/

#include "SDL/SDL.h"
#include "SDL/SDL_opengl.h"
#include <stdbool.h>
//#include <math.h>
//#include <stdio.h>
//#include <stdlib.h>

#include "defines.h"
#include "nograph.h"
#include "path.h"


extern cell MAP[MAP_SIZE_X][MAP_SIZE_Y];

bool CAN_GET_THERE[MAP_SIZE_X][MAP_SIZE_Y];

Q q; // очередь. нужна для нахождения пути

ushort back_path_x[100];
ushort back_path_y[100];
ushort back_path_current = 0;


void
push(ushort x, ushort y, ushort px, ushort py, uint NEW)
{
	CAN_GET_THERE[x][y] = true;

	MAP[x][y].move_cost = NEW;
	MAP[x][y].parent_x = px;
	MAP[x][y].parent_y = py;
	
	q.qx[q.tail] = x;
	q.qy[q.tail] = y;
	
	(q.tail)++;
	if (q.tail == q.qu_size) {
		q.tail = 0;
	}
}



uint
process_ZOC (uint cost, ushort x, ushort y, unit *u)
{
	ushort cx, cy, i;
	ushort ap = u->type->ap;

	for(i=0; i<6; i++) //обходим все прилежащие вершины
		if(get_close_hex_pos(x, y, i, &cx, &cy))
			if(MAP[cx][cy].unit && MAP[cx][cy].unit->player != u->player)
				// сделать так, что б ход заканчивался на этой клетке
				if(cost % ap)
					cost += (ap - (cost % ap));

	return(cost);
}



void
try_push(unit *u, ushort x, ushort y, ushort px, ushort py)
{
	// проверка на меньшще нуля не нужна из-за типа
	if ((x >= MAP_SIZE_X) || (y >= MAP_SIZE_Y))
		return;

	//что бы не проходить через другх
	//if (MAP[x][y].unit && MAP[x][y].unit->player != u->player)
	if (MAP[x][y].unit) 
		return;

	uint NEW = MAP[px][py].move_cost + u->type->terrain[MAP[x][y].type];

	NEW = process_ZOC(NEW, x, y, u);

	if ((MAP[x][y].move_cost > NEW)) //if(OLD > NEW)
		if(u->type->terrain[MAP[x][y].type] <= u->type->ap)
			push(x, y, px, py, NEW);
}



bool
pop(ushort *x, ushort *y)
{
	if (q.head == q.tail) {
		return(false);	// Q is empty
	}
	
	*x = q.qx[q.head];
	*y = q.qy[q.head];
	
	(q.head)++;
	if (q.head == q.qu_size)
		q.head = 0;
		
	return(true);
}



bool
init_q ()
{
	int size = MAP_SIZE_X*MAP_SIZE_Y;
	
	q.qx = (malloc(size * sizeof(ushort)));
	q.qy = (malloc(size * sizeof(ushort)));
	
	if (q.qx == NULL || q.qy == NULL)
		return(false);
		
	q.tail = 0;
	q.head = 0;
	q.qu_size = size;
	
	return(true);
}



void
fill_map(unit *u)
{
	ushort x, y;
	for (y=0; y<MAP_SIZE_Y; y++)
		for (x=0; x<MAP_SIZE_X; x++)
		{
			MAP[x][y].move_cost = 30000;
			CAN_GET_THERE[x][y] = false;
		}
	
	
	push(u->mx, u->my, u->mx, u->my, 0); //push start point
	
	ushort i, x2, y2;
	while (pop(&x, &y))
		for(i = 0; i < 6; i++)
			if(get_close_hex_pos(x, y, i, &x2, &y2))
				try_push(u, x2, y2, x, y);
}



void
get_path(unit *u, ushort ex, ushort ey)
{
	back_path_current = 0;

	ushort x = ex, y = ey, tmpx, tmpy;
	while ((x != u->mx) || (y != u->my))
	{
		back_path_x[back_path_current] = x;
		back_path_y[back_path_current] = y;
		back_path_current++;
		
		tmpx = MAP[x][y].parent_x;
		tmpy = MAP[x][y].parent_y;
		x = tmpx;
		y = tmpy;
	}
	back_path_x[back_path_current] = x;
	back_path_y[back_path_current] = y;
	back_path_current++;
}


